package com.liangwei.jd.service;

import com.google.common.base.Strings;

import com.liangwei.jd.vo.LoginResult;
import com.liangwei.jd.vo.UserInfoVo;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Objects;
import java.util.Set;

import static com.liangwei.jd.service.Constant.*;


/**
 * 干嘛写注释，就是不叫你看懂
 *
 * @author liangweih
 * @since 2019/3/14 15:39
 */
@Component("loginService")
public class LoginService {
    private static final Logger log = LoggerFactory.getLogger(LoginService.class);
    private static String[] filelist;
    private static BufferedImage[] yt;

    static {
        File file = new File(YT_IMAGER_URL);
        filelist = file.list();
        yt = new BufferedImage[filelist.length];
        for (int i = 0; i < filelist.length; i++) {
            log.info("原图加载 name:{}", filelist[i]);
            yt[i] = FileUtil.GetBufferedImage(FileUtil.fileToBase64(YT_IMAGER_URL + File.separator + filelist[i]));

        }

    }


    public LoginResult login(ChromeDriver browser, UserInfoVo userInfoVo) {
        LoginResult loginResult;
      browser.findElementByXPath("//*[@id=\"content\"]/div[2]/div[1]/div/div[3]/a").click();
       // browser.switchTo().frame(browser.findElementByTagName("iframe"));
        browser.findElementById(ELEMENT_USERNAME_ID).sendKeys(userInfoVo.getUsername());
        browser.findElementById(ELEMENT_PASSWORD_ID).sendKeys(userInfoVo.getPassword());
        String js = "document.getElementById(\"" + ELEMENT_SUBMIT_ID + "\").click()";
        browser.executeScript(js);

        int t = 0;
        while (t < 50) {
            String datu = null, datus = null;
            for (int i = 1; i < 50; i++) {
                CommonlyUtil.sleep(2000L);
                try {
                    datus = browser.findElementByXPath(ELEMENT_CODE_IMG_SRC_XPATH).getAttribute("src");
                    datu = datus.replace("data:image/png;base64,", "");
                    if(!Strings.isNullOrEmpty(datu))
                    {
                        break;
                    }

                } catch (Exception e) {
                    log.debug("等待验证码{}次", i);
                }

                if (i % 5 == 0) {
                    loginResult = waitForLogin(browser, userInfoVo);
                    if (loginResult != null) {
                        return loginResult;
                    }

                }

            }
            //获取不到验证码，可能不需要，可能网络连接失败
            if (Strings.isNullOrEmpty(datu)) {
                loginResult = waitForLogin(browser, userInfoVo);
                if (loginResult == null) {
                    loginResult = new LoginResult();
                    loginResult.setError("获取验证码失败，请检查网络");
                    loginResult.setUsername(userInfoVo.getUsername());
                    loginResult.setSuccess(false);
                }

                return loginResult;
            } else {
                loginResult = slide(browser, userInfoVo, datu);
                if (loginResult != null) {
                    return loginResult;
                }

                try {
                    WebElement aa = browser.findElementByXPath(ELEMENT_CODE_IMG_SRC_XPATH);

                    if ( !aa.getAttribute("src").equals(datus)) {
                        continue;
                    }
                } catch (Exception e) {
                    log.error("查询不到验证码");
                }

                loginResult = waitForLogin(browser, userInfoVo);

                if (loginResult != null) {
                    return loginResult;
                }
            }


            t++;
        }
        loginResult = new LoginResult();
        loginResult.setError("40次登录失败");
        loginResult.setUsername(userInfoVo.getUsername());
        loginResult.setSuccess(false);
        return loginResult;
    }

    private static LoginResult waitForLogin(ChromeDriver browser, UserInfoVo userInfoVo) {
        LoginResult loginResult;
        String error, error1;
        for (int i = 0; i < 10; i++) {

            CommonlyUtil.sleep(2000L);

            try {
                error = browser.findElementById("loginpwd_error").getText();

            } catch (Exception e) {
                error = null;

            }

            try {

                error1 = browser.findElementById("loginname_error").getText();
            } catch (Exception e) {

                error1 = null;
            }

            if (!Strings.isNullOrEmpty(error) || !Strings.isNullOrEmpty(error1)) {
                loginResult = new LoginResult();
                loginResult.setError(error==null?error1:error);
                loginResult.setUsername(userInfoVo.getUsername());
                loginResult.setSuccess(false);
                return loginResult;
            }
            String text = null;
            try {
                text = browser.switchTo().alert().getText();
            } catch (NoAlertPresentException exception) {

            }
            if (!Strings.isNullOrEmpty(text)) {
                loginResult = new LoginResult();
                loginResult.setError(text);
                loginResult.setUsername(userInfoVo.getUsername());
                loginResult.setSuccess(false);
                return loginResult;
            }
            if (browser.getCurrentUrl().contains("aq.jd.com/certified/index")) {
                loginResult = new LoginResult();
                loginResult.setError("账户需要验证");
                loginResult.setUsername(userInfoVo.getUsername());
                loginResult.setSuccess(false);
                return loginResult;
            }
            if (!browser.getCurrentUrl().contains("https://jzt.jd.com/gw")) {

                Set<Cookie> setC = browser.manage().getCookies();
                loginResult = new LoginResult();
                loginResult.setCookies(setC);
                loginResult.setSuccess(true);
                loginResult.setUsername(userInfoVo.getUsername());
                return loginResult;
            }

        }

        return null;
    }

    private LoginResult slide(ChromeDriver browser, UserInfoVo userInfoVo, String datu) {
        LoginResult loginResult;

        if (Objects.isNull(filelist)) {
            loginResult = new LoginResult();
            loginResult.setError("原图不存在");
            loginResult.setUsername(userInfoVo.getUsername());
            loginResult.setSuccess(false);
            return loginResult;
        }

        BufferedImage qkt;
        int x = 0;
        for (int i = 0; i < filelist.length; i++) {

            qkt = FileUtil.GetBufferedImage(datu);
            if (compaisonImage(qkt, yt[i])) {
                x = CommonlyUtil.getI(qkt, yt[i]);
            }
        }

        log.info("x-{}",x);

        // x = analysisX(x);
        if (x < 10) {
            browser.findElementByClassName(ELEMENT_CODE_REFRESH_CLASSNAME).click();
            log.error("验证码匹配失败");
           // FileUtil.base64ToFile(ERROR_IMAGER_URL, datu, System.currentTimeMillis() + ".png");
        } else {
            try {
                // browser.findElementByXPath("//*[@id=\"JDJRV-wrap-paipaiLoginSubmit\"]/div/div/div/div[2]/div[3]")

                CommonlyUtil.move(browser, browser.findElementByClassName(ELEMENT_CODE_SLIDER_CLASSNAME), x);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private int analysisX(int x) {
        //        if (x > 0) {
        //
        //            int multiple = (new Double(Math.floor(x / DEVIATION_PIXEL))).intValue();
        //
        //            double y = (COEFFICIENT + (0.01 * multiple));
        //            int w = CODE_WIDTTH / CUTTING_VALUE;
        //
        //            int block = x / w;
        //            System.out.println((int) Math.rint(x * y) + ((COMPENSATE_VALUE - block)*(x/95)));
        //            System.out.println(((COMPENSATE_VALUE - block)*(x/95)));
        //            return (int) Math.rint(x * y) + ((COMPENSATE_VALUE - block)*(x/95));
        //        }


        if (x > 0) {

            double y = 0.01 * (x / 19.66);
            return (int) Math.round(x * (0.89 - y)) + 3;

        }

        return 0;

    }

    private static boolean compaisonImage(BufferedImage qkt, BufferedImage yt) {
        for (int i = 0; i < qkt.getWidth(); i++) {
            for (int j = 0; j < qkt.getHeight(); j++) {
                if (qkt.getRGB(i, j) == yt.getRGB(i, j)) {
                    if (i > 35) {
                        return true;
                    }

                } else {
                    return false;
                }
            }
        }
        return false;
    }
}
